package me.fung.wubi.worker.printer

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.runBlocking
import me.fung.wubi.base.define.table.CodeTable
import me.fung.wubi.base.define.value.CodeList
import me.fung.wubi.base.define.value.toCode
import me.fung.wubi.base.io.localObject
import java.io.File
import java.nio.charset.Charset
import java.text.SimpleDateFormat
import java.util.*

private const val TAG_WUBI_FACTORY_TABLE_CONTENT = "WUBI_FACTORY_TABLE_CONTENT"
private const val TAG_WUBI_FACTORY_UUID = "WUBI_FACTORY_UUID"
private const val TAG_WUBI_FACTORY_SERIAL_NUMBER = "WUBI_FACTORY_SERIAL_NUMBER"
private const val TAG_TAG_WUBI_FACTORY_AUTHOR = "WUBI_FACTORY_AUTHOR"
private const val AUTH = "https://space.bilibili.com/19497971"

class IBusTextPrinter(
    override var outPutFile: File,
) : BaseTablePrinter() {
    override fun buildContent(table: CodeTable, config: PrintConfig): String = runBlocking(Dispatchers.IO) {
        val contentDeferred = async() {
            buildTableContent(table)
        }
        loadTemplate().apply {
            replace(TAG_WUBI_FACTORY_UUID.toRegex(), UUID.randomUUID().toString())
            replace(TAG_WUBI_FACTORY_SERIAL_NUMBER.toRegex(), buildSerialNumber())
            replace(TAG_TAG_WUBI_FACTORY_AUTHOR.toRegex(), AUTH)
            replace(TAG_WUBI_FACTORY_TABLE_CONTENT.toRegex(), contentDeferred.await())
        }
    }

    private fun buildSerialNumber(): String {
        return SimpleDateFormat("YYYYMMDDhhmmss").format(Date())
    }

    private fun loadTemplate(
        filename: String = localObject.path() + "template/ibus.txt",
        charset: Charset = Charsets.UTF_8,
    ): String {
        val file = File(filename)
        return file.readText(charset)
    }

    private fun buildTableContent(table: CodeTable): String = buildString {
        CodeList.value.forEach { codeValue: String ->
            val item = table.itemOrNull(codeValue.toCode())
            if (item?.isNotEmpty() == true) {
                val code = item.code.value
                for (i in 0 until item.size) {
                    append(code)
                    append("\t")
                    append(item[i].value)
                    append("\t")
                    append(kotlin.math.max(1000 - i, 1))
                    appendLine()
                }
            }
        }
    }
}